/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package neuronalenetzeelearning.model;

import java.lang.Math;

/**
 * Legt die Rechnung für die Ausgabewerte der Knoten, abhängig von der ausge-
 * wählten Aktivierungsfunktion fest.
 * @author Maria
 */
public enum StepFunction {

    LINEARLINEAR,
    SIGMOIDLINEAR,
    HEAVISIDELINEAR;

    /**
     * Aktivierungsfkt ist eine Methode, die besagt welche Werte eine Knoten weiter-
     * gibt. Sie werden hier beschrieben und in der jeweiligen Lernregel durch eine
     * Abfrage aufgegriffen.
     * 1. Methode für Sigmoid
     *  --> Ausgabewert_neuronJ = 1 /(1+exp(-nettoInput_J/schwellenwert_J))
     *
     * 2. Methode für die Schwellenwertfkt
     *  --> Ausgabewert_neuronJ =   wenn (nettoInput > schwellenwert) ausgabe= wert_1
     *                              sonst ausgabe = wert_2
     * Parameter: nettoInput
     */
    /**
     * @param node
     * @return
     */
    public double calculate(Node node) {
        switch (this) {
            case LINEARLINEAR:
                return linearLinear(node);
            case SIGMOIDLINEAR:
                return sigmoidLinear(node);
            case HEAVISIDELINEAR:
                return heavisideLinear(node);

            /**
            case SIGMOID: return sigmoid(node);
            case LINEAR: return linearLinear(node);
            case HEAVISIDE: return heavisideLinear(node);
             */
            default:
                return 0;
        }
    }

    /**
     * linear:wenn input>thresh dann output=1, sonst 0
     * linear: wenn output>0 dann raus= input, sonst 0
     * @param node
     * @return Ausgabewert von node (Ausgabe(x)=1 für -0.5<=x<=0.5 und Ausgabe(x)=0, sonst)
     */
    private double linearLinear(Node node) {
        double out1;
        double out2;
        double x = node.nettoinput();
        if (x >= node.getThreshold()) {
            out1 = 1;
            out2 = x;
            node.setOutputValue(x);
        } else {
            out2 = 0;
            node.setOutputValue(0);
        }

        return out2;
    }

    /**

     * sigmoid: wenn input>0 dann output=formel, sonst 0
     * linear:wenn input>thresh dann raus=1, sonst 0
     * @param node
     * @return Ausgabewert von node (Ausgabe(x)=1 für -0.5<=x<=0.5 und Ausgabe(x)=0, sonst)
     */
    private double sigmoidLinear(Node node) {
        double out1;
        double out2;
        double x = node.nettoinput();
        if (x > 0) {
            out1 = 1 / (1 + Math.exp(-x / 2));
        } else {
            out1 = 0;
        }
        if (out1 >= node.getThreshold()) {
            out2 = out1;
        } else {
            out2 = 0;
        }

        node.setOutputValue(out2);
        return out2;
    }

    /**
     * heaviside: wenn input>thresh dann output=input, sonst 0
     * linear: wenn output>0 dann raus= input, sonst 0
     * @param node
     * @return Ausgabewert von node (Ausgabe(x)=1 für x>=0 und Ausgabe(x)=0, sonst)
     */
    private double heavisideLinear(Node node) {
        double out1;
        double out2;
        double x = node.nettoinput();
        if (x >= node.getThreshold() && x > 0) {
            out1 = x;
            out2 = x;
            node.setOutputValue(out2);
        } else {
            out2 = 0;
            node.setOutputValue(0);
        }
        return out2;

    }
}
